******************************************************************************
* AnimDemo
*
* (C)  Copyright Apple Computer, Inc. 1988
* All rights reserved.
*
* by Jim Mensch
* 7/13/88
*
* This program is designed to show 3 different styles of animation techniques
* that can be used on the Apple IIgs.
*
* NOTE: This program shows simple animation techniques that can be used as
* templates for your own applications. Every attempt has been made to insure
* maximum understandability of the source code. Speed has been sacrificed for
* clarity in a few of the samples. Two techniques that are not used here but
* are worth mentioning using the verticle count register to know when to
* start drawing (Discussed in IIgs tech note #39) and Shielding the cursor
* when using the event manager ( IIgs tech note #34).
*
* Files:            System  macros and equates
*
*
*
* Modification History:
*
* Version 1.0   JIm Mensch
*
*      7/13/88      Initial Release
*
*
*******************************************************************************
*                                                                    *
*             Apple IIGS Source Code Sampler, Volume I               *
*                                                                    *
*             Copyright (c) Apple Computer, Inc. 1988                *
*                       All Rights Reserved                          *
*                                                                    *
*            Written by Apple II Developer Tech Support              *
*                                                                    *
*                                                                    *
*                                                                    *
*  ----------------------------------------------------------------  *
*                                                                    *
*     This program and its derivatives are licensed only for         *
*     use on Apple computers.                                        *
*                                                                    *
*     Works based on this program must contain and                   *
*     conspicuously display this notice.                             *
*                                                                    *
*     This software is provided for your evaluation and to           *
*     assist you in developing software for the Apple IIGS           *
*     computer.                                                      *
*                                                                    *
*     DISCLAIMER OF WARRANTY                                         *
*                                                                    *
*     THE SOFTWARE IS PROVIDED "AS IS" WITHOUT                       *
*     WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,               *
*     WITH RESPECT TO ITS MERCHANTABILITY OR ITS FITNESS             *
*     FOR ANY PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO             *
*     THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH            *
*     YOU.  SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU (AND            *
*     NOT APPLE OR AN APPLE AUTHORIZED REPRESENTATIVE)               *
*     ASSUME THE ENTIRE COST OF ALL NECESSARY SERVICING,             *
*     REPAIR OR CORRECTION.                                          *
*                                                                    *
*     Apple does not warrant that the functions                      *
*     contained in the Software will meet your requirements          *
*     or that the operation of the Software will be                  *
*     uninterrupted or error free or that defects in the             *
*     Software will be corrected.                                    *
*                                                                    *
*     SOME STATES DO NOT ALLOW THE EXCLUSION                         *
*     OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY              *
*     NOT APPLY TO YOU.  THIS WARRANTY GIVES YOU SPECIFIC            *
*     LEGAL RIGHTS AND YOU MAY ALSO HAVE OTHER RIGHTS                *
*     WHICH VARY FROM STATE TO STATE.                                *
*                                                                    *
*                                                                    *
**********************************************************************


                    mcopy animdemo.macros
                    copy 2/ainclude/E16.memory

DPHandle            gequ 0
DPPointer           gequ DPHandle+4
Counter             gequ DPPointer+4
LastTick            gequ Counter+2
temp1               gequ LastTick+2
temp2               gequ temp1+2
LinePt              gequ temp2+2
ScreenTab           gequ LinePt+4
MyBitMap            gequ ScreenTab+4
MyBitMask           gequ MyBitMap+4
CurX                gequ MyBitMask+4
CurY                gequ CurX+2
DDPoint1            gequ CurY+2
DDPoint2            gequ DDPoint1+4
DDPoint3            gequ DDPoint2+4
DDTemp              gequ DDPoint3+4
DDXInc              gequ DDTemp+4
DDYInc              gequ DDXInc+2

ScreenMode          gequ 0
ScreenWidth         gequ 320

                    EJECT
*******************************************************************************
*
AnimDemo            start
*
* Description:      This is the main loop of the animation demo
*
*
* Inputs:           None
*
* Outputs:          None
*
* External Refs:
*                   Import InitTools
*                   Import InitApp
*                   Import MainLoop
*                   Import CloseApp
*                   Import CloseTools
*                   Import QuitParms
*
* Entry Points:
*
*******************************************************************************
                    Using globals

                    jsr InitTools
                    jsr InitApp
                    jsr MainLoop
                    jsr CloseApp
                    jsr CloseTools

                    _Quit QuitParms

                    end


                    EJECT
*******************************************************************************
*
Globals             data
*
* Description:      Data used throughout the program
*
*
* Inputs:           None
*
* Outputs:          None
*
* External Refs:    None
*
* Entry Points:
*                   Export QuitParms
*
*******************************************************************************
MyID                ds 2                ; application ID
QuitParms           dc i4'0'            ; standard parms to make the quit call
                    dc i2'$00'          ; return to the launching application
                    dc i2'0'

DTSString           dc c'Apple IIgs Power to Animate',i1'0'
AutString           dc c'By Jim Mensch Apple DTS',i1'0'

Trigger             dc i2'0'

EventRecord         ANOP
EventWhat           ds 2
EventMessage        ds 4
EventWhen           ds 4
EventWhere          ds 4
EventModifiers      ds 2

Rect                ds 8

BitMap              dc i2'$7700,$7777,$0077' ; Bit maps of our animated character
                    dc i2'$6607,$7667,$7066'
                    dc i2'$6676,$7667,$6766'
                    dc i2'$6776,$7777,$6776'
                    dc i2'$6776,$0000,$6776'
                    dc i2'$7777,$0000,$7777'
                    dc i2'$7777,$0000,$7777'
                    dc i2'$6776,$0000,$6776'
                    dc i2'$6776,$7777,$6776'
                    dc i2'$6676,$7667,$6766'
                    dc i2'$6607,$7667,$7066'
                    dc i2'$7700,$7777,$0077'

BitMask             dc i2'$FF00,$FFFF,$00FF' ; Mask of our animated character
                    dc i2'$FF0F,$FFFF,$F0FF' ; to be used for seethru drawing
                    dc i2'$FFFF,$FFFF,$FFFF'
                    dc i2'$FFFF,$FFFF,$FFFF'
                    dc i2'$FFFF,$0000,$FFFF'
                    dc i2'$FFFF,$0000,$FFFF'
                    dc i2'$FFFF,$0000,$FFFF'
                    dc i2'$FFFF,$0000,$FFFF'
                    dc i2'$FFFF,$FFFF,$FFFF'
                    dc i2'$FFFF,$FFFF,$FFFF'
                    dc i2'$FF0F,$FFFF,$F0FF'
                    dc i2'$FF00,$FFFF,$00FF'

MyDP                ds 2                ; My zero page storage

                    end
                    
                    EJECT
*******************************************************************************
*
InitTools           start
*
* Description:      Routine that loads and starts up all the tools that we will
*                   be using in this program
*
*
* Inputs:           None
*
* Outputs:          None
*
* External Refs:    
*                   Import FatalError
*
* Entry Points:     None
*
*******************************************************************************
                    using Globals
;
;   Tool Direct page offsets here
;
QDDPage             equ $0000
EMDPage             equ QDDPage+$0300
SEQDPage            equ EMDPage+$0100
ToolDPSize          equ SEQDPage+$0200

                    phk                 ; Save program bank register and
                    plb                 ; load it as the data bank register

                    tdc
                    sta MyDP            ; Save direct register

                    _TLStartup          ; Start Tool Locator

                    PushWord            ; Space for result
                    _MMStartup          ; Start memory manager
                    PullWord MyID       ; Save it for later use

                    _MTStartup          ; Start up Misc Tools

                    _IMStartup          ; Start integer math toolset

;                   PushLong #ToolTable ; Pointer to Tool table
;                   _LoadTools          ; Load all RAM based tools
;                   bcc IT0005          ; Carry clear means no error
;                   brl FatalError      ; Tools can't be loaded. Fatal error!

IT0005              ANOP

; Get memory for Tool Direct pages

                    PushLong #0         ; Room for result
                    PushLong #ToolDPSize ; Number of bytes needed
                    PushWord MyID       ; ID of this application
                    PushWord #AttrLocked+attrFixed+attrPage+attrBank
                    PushLong #0         ; Allocate them in bank 0
                    _NewHandle
                    bcc IT0010          ; Test carry for error
                    brl FatalError      ; If no memory we got a fatal error!

IT0010              PullLong DPHandle   ; Retrieve handle to our DPage area

                    lda [DPHandle]      ; Dereference the handle to get a ptr
                    sta DPPointer       ; to our direct page area and save it.

                    PushWord DPPointer  ; QuickDraw uses 3 pages of Dpage
                    PushWord #ScreenMode ; Used to set all master SCB's
                    PushWord #0         ; Zero means use default buf size
                    PushWord MyID       ; Application ID for allocating data
                    _QDStartup          ; Start QuickDraw, turn on SHR Screen
                    bcc IT0015
                    brl FatalError      ; If it can't be started then bomb

IT0015              ANOP
                    lda DPPointer       ; Create address for Event Mgr DPage by
                    clc                 ; loading in the pointer to the start
                    adc #EMDPage        ; of DPage and adding Evt Mgr offset.
                    pha                 ; Now push it on the stack.
                    PushWord #20        ; Size of event queue.
                    PushWord #0         ; MouseClamp values.
                    PushWord #ScreenWidth ; These will clamp mouse to screen
                    PushWord #0         ; area only.
                    PushWord #200
                    PushWord MyID
                    _EMStartup          ; Start the event manager
                    bcc IT0020
                    brl FatalError      ; Event manager is also a must
IT0020              ANOP

                    RTS
ToolTable           dc i2'2'
                    dc i2'25,$0100'     ; note synth
                    dc i2'26,$0100'     ; note sequencer

                    end
                    
                    
                    EJECT
*******************************************************************************
*
FatalError          start
*
* Description:      Routine that is called whenever a tool sends back an error
*                   that can not be recovered from. This routine prints the
*                   error on the screen, waits for a keypress then quits back
*                   to whoever started this application up!
*
*
* Inputs:           A = Error number
*
* Outputs:          NONE (program exits)
*
* External Refs:
*                   Import CloseTools
*
* Entry Points:     NONE
*
*******************************************************************************
                    using Globals

                    pha                 ; Push the error code
                    PushLong #errNumStr ; Address of storage area
                    PushWord #4         ; Length of string
                    _Int2Hex

                    _GrafOff            ; If QD Started, shut off graphics

                    PushLong #ErrStr    ; Write error message to the screen
                    _WriteCString

                    pha                 ; Space for result
                    PushWord #0         ; No echo
                    _ReadChar           ; Wait for a key to be pressed
                    pla                 ; Discard the key

                    jsr CloseTools      ; Shut down all the tools in case
;                                         any got started up

                    _Quit QuitParms     ; Quit back to where we came from.

                    brk $FF             ; If the quit fails then just break
                    
ErrStr              dc c'A fatal error has occured $'
ErrNumStr           dc c'xxxx   press any key to exit',i1'0'

                    end

                    EJECT
*******************************************************************************
*
CloseTools          start
*
* Description:      Closes all the tools that were started when the application
*                   called InitTools.
*
*
* Inputs:           None
*
* Outputs:          None
*
* External Refs:    None
*
* Entry Points:     None
*
*******************************************************************************
                    using Globals

                    _GrafOff
                    _EMShutDown
                    _QDShutDown
                    _MTShutDown

                    PushLong DPHandle   ; Dispose of all the DP memory
                    _DisposeHandle

                    PushWord MyID
                    _MMShutDown
                    _TLShutDown
                    rts
                    end


                    EJECT
*******************************************************************************
*
InitApp             start
*
* Description:      This procedure will draw the initial screen display and
*                   install all the heartbeat tasks for the various animation
*                   routines.
*
*
* Inputs:           None
*
* Outputs:          None
*
* External Refs:    None
*                   Import ScrollTask
*                   Import LightTask
*                   Import TrigrTask
*
* Entry Points:     None
*
*******************************************************************************
                    using Globals

                    Stz LinePt          ; use line pt as temp flag!

                    PushWord #5         ; Erase Screen to DkGreen
                    _SetSolidPenPat

                    PushLong #ScrnRect
                    _PaintRect

                    PushWord #0
                    _SetSolidPenPat

                    PushLong #Marq1Rect ; Erase the Marquee area to black
                    _PaintRect

                    PushLong #CoinRect  ; Erase the coin area to black
                    _PaintRect

                    Inc CoinRect        ; InsetRect(CoinRect,-1,-1)
                    inc CoinRect+2
                    dec CoinRect+4
                    dec CoinRect+6

                    PushWord #4         ; give the coin rectangle a green boarded
                    _SetSolidPenPat

                    PushLong #Rect
                    _FrameRect


                    lda #20             ; set up a rectangle for the first
                    sta Rect            ; Marquee light in the top row 
                    sta Rect+2          ; 
                    lda #30
                    sta Rect+4
                    sta Rect+6

                    PushWord #9         ; draw then in Yellow
                    _SetSolidPenPat
                    
                    jsr DrawLightsH     ; and draw a row of horizontal lights

                    lda #30
                    sta Rect+2          ; update the left and right values of
                    lda #40             ; the rectangle to start 10 pixels over
                    sta Rect+6          
                    
                    PushWord #1         ; set the color to dark gray
                    _SetSolidPenPat     
                    
                    jsr DrawLightsH     ; and draw a row of gray lights next to the yellow ones
                    
                    lda #100            ; Now create the rectangle for the bottom row of 
                    sta Rect            ; lights
                    lda #30
                    sta Rect+2
                    lda #110
                    sta Rect+4
                    lda #40
                    sta Rect+6

                    jsr DrawLightsH     ; and draw this row in Dk Gray

                    lda #20             ; now reset to draw the yellow lights in this row
                    sta Rect+2
                    lda #30
                    sta Rect+6
                    
                    PushWord #9
                    _SetSolidPenPat

                    jsr DrawLightsH

; Now draw the vertical lights
                    lda #20             ; set up a rectangle for the first
                    sta Rect            ; Marquee light in the left column 
                    sta Rect+2          ; 
                    lda #30
                    sta Rect+4
                    sta Rect+6

                    PushWord #9         ; draw then in Yellow
                    _SetSolidPenPat
                    
                    jsr DrawLightsV     ; and draw a Col of vert lights


                    lda #30
                    sta Rect            ; update the top and bottom values of
                    lda #40             ; the rectangle to start 10 pixels over
                    sta Rect+4          
                    
                    PushWord #1         ; set the color to dark gray
                    _SetSolidPenPat     
                    
                    jsr DrawLightsV     ; and draw a row of gray lights under the yellow 

                    lda #30             ; Now create the rectangle for the bottom row of 
                    sta Rect            ; lights
                    lda #290
                    sta Rect+2
                    lda #40
                    sta Rect+4
                    lda #300
                    sta Rect+6

                    jsr DrawLightsV     ; and draw this row in Dk Gray

                    lda #20             ; now reset to draw the yellow lights in this row
                    sta Rect
                    lda #30
                    sta Rect+4
                    
                    PushWord #9
                    _SetSolidPenPat

                    jsr DrawLightsV

                    PushWord #15        ; Now, Erase the text area to white
                    _SetSolidPenPat

                    PushLong #Marq2Rect
                    _PaintRect

                    PushWord #0         ; Draw the strings in the marquee
                    _SetSolidPenPat

                    PushWord #50
                    PushWord #60
                    _MoveTo

                    PushLong #DTSString
                    _DrawCString

                    PushWord #62
                    PushWord #80
                    _MoveTo

                    PushLong #AutString
                    _DrawCString

                    PushLong #0         ; Get the address of the screen 
                    PushWord #1         ; address table for use in our
                    _GetAddress         ; animation routines
                    PullLong ScreenTab

                    lda #BitMap         ; Now create a pointer to our bitmap
                    sta MyBitMap
                    lda #BitMap|-16
                    sta MyBitMap+2

                    lda #BitMask        ; Now create a pointer to our bitMask
                    sta MyBitMask
                    lda #BitMask|-16
                    sta MyBitMask+2

                    lda #20             ; initialize the starting location
                    sta CurX            ; of the coin.
                    lda #141
                    sta CurY

                    lda #1              ; and set the current increment
                    sta DDxInc
                    sta DDyInc

                    PushLong #ScrollTask ;Install the scrolling routine in
                    _SetHeartBeat       ; Heart beat queue

                    PushLong #LightTask ; install the Marquee light
                    _SetHeartBeat       ; heartbeat task

                    PushLong #TrigrTask ; and install our heartbeat trigger
                    _SetHeartBeat

                    rts

; The following routine, given the starting rectangle of the first light to draw
; Will draw a horizontal row of 14 lights across the screen at 20 pixel intervals
; 
DrawLightsH         ANOP
                    stz Counter         ; Init the ligh counter
IA001               PushLong #Rect      ; draw the first light
                    _PaintOval

                    lda Rect+2          ; OffsetRect(Rect,20,0)
                    clc                 ; do this by adding 20 to Rect.left
                    adc #20
                    sta Rect+2
                    lda Rect+6          ; and rect.right
                    clc
                    adc #20
                    sta Rect+6

                    ldy Counter         ; bump the counter
                    iny
                    sty Counter
                    cpy #14             ; test to see if we are done
                    bne IA001           ; if not, draw another light
                    rts                 ; if so, then simply end
;
; This routine is the same as above only it creates vertical lights
DrawLightsV         ANOP
                    stz Counter
IA011               PushLong #Rect      ; draw the light
                    _PaintOval

                    lda Rect            ; OffsetRect(Rect,0,20)
                    clc
                    adc #20
                    sta Rect
                    
                    lda Rect+4
                    clc
                    adc #20
                    sta Rect+4
                    
                    ldy Counter         ; Bump the counter
                    iny
                    sty Counter
                    cpy #4
                    bne IA011           ; if not done draw another light
                    rts                 ; if done, then return
                    
ScrnRect            dc i2'0,0,200,320'
Marq1Rect           dc i2'18,18,112,302'
Marq2Rect           dc i2'32,32,98,288'
CoinRect            dc i2'139,38,183,292'

                    end

                    EJECT
*******************************************************************************
*
MainLoop            start
*
* Description:      This routine runs in a continuous loop until the user
*                   presses the mouse button. At that time, it ends. While
*                   it is looping, this routine checks Trigger, if the Trigger
*                   is set, it calls the walk routine to move the coin
*
*
* Inputs:           None
*
* Outputs:          None
*
* External Refs:
*
* Entry Points:
*                   Import DoWalk
*
*******************************************************************************
                    using Globals

                    lda Trigger         ; test VBL Trigger value
                    beq EL0010          ; if its zero then don't move the coin

                    jsr DoWalk          ; Walk a ball around a square
EL0010              ANOP
                    PushWord #0         ; get an event
                    PushWord #$FFFF
                    PushLong #EventRecord
                    _GetNextEvent

                    pla
                    lda EventWhat
                    cmp #1              ; is it a mousedown???
                    bne MainLoop        ; if not get another event
                    rts                 ; if so, then just end
                    end

                    EJECT
*******************************************************************************
*
CloseApp            start
*
* Description:      This routine removes all our heartbeat tasks at the end
*                   of the program.
*
*
* Inputs:           None
*
* Outputs:          None
*
* External Refs:
*                   Import TrigrTask
*                   Import LightTask
*                   Import ScrollTask
*
* Entry Points:
*
*******************************************************************************
                    PushLong #TrigrTask
                    _DelHeartBeat

                    PushLong #ScrollTask
                    _DelHeartBeat

                    PushLong #LightTask
                    _DelHeartBeat

                    rts
                    end


                    EJECT
*******************************************************************************
*
TriggerP            start
*
* Description:      Trigger heartbeat task. Every 1/60 of a second this routine
*                   will set a trigger value. The program can then read this 
*                   value and use it to base our coin animation.
*
*
* Inputs:           None
*
* Outputs:          None
*
* External Refs:    None
*
* Entry Points:     None
*                   Export TrigrTask
*
*******************************************************************************
                    using Globals
TrigrTask           ENTRY
                    dc i4'0'            ; heartbeat task header
TrgTaskCnt          dc i2'3'            ; Number of ticks before running
                    dc i2'$A55A'        ; heartbeat task signature
                    
                    php                 ; save the current proc state
                    REP #$30            ; set long A,I and M
                    lda #1              ; set the trigger to true
                    sta >Trigger        
                    lda #1              ; set the task up to be fired again
                    sta >TrgTaskCnt     ; in 1/60th of a second

                    plp                 ; restore the proc status
                    RTL                 ; and leave this routine
                    end

                    EJECT
*******************************************************************************
*
LightAnim           start
*
* Description:      Marquee ligh animation. This heartbeat task will switch the
*                   color table entries of color 9 and color 1 every 1/10 of
*                   a second. This will give the illusion of moving lights
*                   much like movie theatres used to use.
*
*
* Inputs:           None
*
* Outputs:          None
*
* External Refs:    None
*
* Entry Points:     
*                   Export LightTask
*
*******************************************************************************
LightTask           ENTRY
                    dc i4'0'
LghTaskCnt          dc i2'5'            ; number of ticks before running
                    dc i2'$A55A'        ; heartbeat signature

                    php                 ; save the current processor state
                    Rep #$30            ; and set full 16 bit mode.

                    PushWord #0         ; get the current color table entry
                    PushWord #0         ; for color #9
                    PushWord #9
                    _GetColorEntry
                    pla
                    sta >tempC1         ; and save it for later use

                    PushWord #0         ; and get the color table entry for 
                    PushWord #0         ; color 1
                    PushWord #1
                    _GetColorEntry
                    pla
                    sta >tempC2         ; and save it for later

                    PushWord #0         ; now set the entry for color #1
                    PushWord #1         ; to be that of what #9 was
                    PushWord >tempC1
                    _SetColorEntry

                    PushWord #0         ; and set color #9 to what Color#1
                    PushWord #9         ; was
                    PushWord >tempC2
                    _SetColorEntry


                    lda #6              ; Re-arm the task to be fired again
                    Sta >LghTaskCnt     ; in 1/10th of a second
                    plp                 ; restore the proc status
                    Rtl                 ; and leave
TempC1              ds 2
TempC2              ds 2
                    end

                    EJECT
*******************************************************************************
*
ScrollAnim          start
*
* Description:      This routine will move an area of the screen over 4 pixels
*                   and wrap the stuff that falls off the edge to the end of
*                   the same line (to give the image of circular scrolling).
*                   This routine gets called aprox every 1/30th of a second
*
* Inputs:           None
*
* Outputs:          None
*
* External Refs:
*
* Entry Points:
*                   Export ScrollTask
*
*******************************************************************************
                    using Globals
ScrollTask          ENTRY
                    dc i4'0'            ; Heartbeat task header
ScrTaskCnt          dc i2'2'
                    dc i2'$A55A'
                    
                    phd                 ; save direct register
                    php                 ; and proc status

                    REP #$30            ; turn on full 16 bit mode...
                    lda >MyDP           ; get my Direct page
                    TCD                 ; and make it current

                    lda #46             ; starting scan line
                    sta Counter
                    lda #$E1
                    sta LinePt+2        ; set up high byte of scrn address

SA010               lda Counter         ; get starting address of scan line
                    asl A               ; multiply by 2!
                    tay
                    lda [ScreenTab],y   ; get next line of screen tab
                    sta LinePt          ; store it in our pointer
                    ldy #16             ; start out 8 bytes in...
                    lda [LinePt],y      ; get first byte of area
                    sta temp1           ; save it for later...

                    ldy #142            ; end of rect to scroll
SA020               lda [LinePt],y      ; get byte to scroll
                    tax                 ; save it in X
                    lda temp1           ; get proper byte value
                    sta [LinePt],y      ; now save it...
                    txa                 ; get saved value
                    sta temp1           ; and save it...
                    dey
                    dey
                    cpy #14             ; did we store the last one???
                    bne SA020
                    inc Counter         ; go to next line
                    lda Counter
                    cmp #82             ; are we done yet???
                    bne SA010           ; nope... not yet!

                    lda #2              ; reset the task timer to 2 60th
                    sta >ScrTaskCnt     ; of a second (1/30th)

                    plp                 ; restore the previous processor flags
                    pld                 ; and the direct page register

                    rtl
                    end

                    EJECT
*******************************************************************************
*
DoWalk              start
*
* Description:      This routine erases the coin from the screen, when the
*                   coin hits an edge, this routine adjusts the increments
*                   properly.
*
*
* Inputs:           None
*
* Outputs:          None
*
* External Refs:
*                   Import DoErase
*                   Import DoDraw
*
* Entry Points:
*
*******************************************************************************
                    using Globals


                    stz Trigger         ; clear the trigger for next time
                    jsr DoErase         ; erase the coin
                    lda CurX            ; test to see if we hit the left
                    cmp #20             ; edge
                    blt DW005           ; if so, then change directions
                    cmp #140            ; test the right edge
                    blt DW010           ; if not exceeded then check top & bottom
DW005               lda #0              ; this will reverse the direction of
                    SEC                 ; the coins horiz movement by negating
                    SBC DDxInc          ; the current x increment
                    sta DDxInc

DW010               lda CurY            ; now test the top and bottom
                    cmp #140            ; past the top?
                    blt DW015           ; if so, change dir
                    cmp #170            ; past the bottom?
                    blt DW020           ; if not skip the next section
DW015               lda #0              ; negate the vertical increment
                    sec
                    sbc DDyInc
                    sta DDyInc

DW020               ANOP
                    lda CurX            ; now that the increment is correct
                    clc                 ; bump our location counters to
                    adc DDxInc          ; the new position
                    sta CurX
                    lda CurY
                    clc
                    adc DDyInc
                    sta CurY
                    jsr DoDraw          ; and re-draw the coin
DW030               ANOP
                    rts
                    end

                    EJECT
*******************************************************************************
*
DoErase             start
*
* Description:      This erases the coin from its current location
*
*
* Inputs:           None
*
* Outputs:          None
*
* External Refs:
*
* Entry Points:
*
*******************************************************************************
                    using Globals

; First calculate the starting scan line *2 and the ending scanline *2. Place
; the starting scan line into the X register and the ending in DDTemp

                    lda CurY            ; get the Y posn and multiply it by 2
                    asl A               ; to get the current screen line offset 
                    tax                 ; store for later use..
                    clc                 ; add 24 to it (12 scan lines *2)
                    adc #24             ; to make the terminating value for
                    sta DDTemp          ; our loop

; next calculates the memory location of the upper left hand corner
; of our object on the screen. This routine uses the scan line address table
; given to us by quickdraw. 
DE010               txy                 ; retrieve the current scan line index
                    lda CurX            ; get XCord in bytes. and Add it to
                    clc                 ; the address of the current ycord scan
                    adc [ScreenTab],y   ; line to create the screen address. 
                    sta DDPoint1        ; Save it in Direct page so we can use
                    lda #$E1            ; it as a long pointer. NOTE: The screen
                    sta DDPoint1+2      ; is always in bank $E1
; Now that DDPoint1 contains the pointer we need start copying Black over the 
; screen area that the coin was in, two bytes at a time.

                    ldy #$0000          ; zero the index
DE0020              lda #$0000          ; erase with black...
                    sta [DDPoint1],y    ; save it to the screen
                    iny                 ; bump our line counter 2
                    iny
                    cpy #6              ; are we done with current line???
                    bne DE0020          ; if not do another word
                    inx                 ; if so bump the screen line tbl offset
                    inx                 ; by two
                    cpx DDTemp          ; see if we finished the whole picture
                    bne DE010           ; if not, draw the next line
                    rts                 ; if so, then end.
                    end

                    EJECT
*******************************************************************************
*
DoDraw              start
*
* Description:      This draws the coin at its current location
*
*
* Inputs:           None
*
* Outputs:          None
*
* External Refs:
*
* Entry Points:
*
*******************************************************************************
                    using Globals

; First calculate the starting scan line *2 and the ending scanline *2. Place
; the starting scan line into the X register and the ending in DDTemp

                    lda CurY            ; get the Y posn and multiply it by 2
                    asl A               ; to get the current screen line offset 
                    tax                 ; store for later use..
                    clc                 ; add 24 to it (12 scan lines *2)
                    adc #24             ; to make the terminating value for
                    sta DDTemp          ; our loop

                    lda MyBitMap        ; get address for my coin data
                    sta DDPoint2        ; and store it in a direct page ptr
                    lda MyBitMap+2
                    sta DDPoint2+2

; next calculates the memory location of the upper left hand corner
; of our object on the screen. This routine uses the scan line address table
; given to us by quickdraw. 
DD010               txy                 ; retrieve the current scan line index
                    lda CurX            ; get XCord in bytes. and Add it to
                    clc                 ; the address of the current ycord scan
                    adc [ScreenTab],y   ; line to create the screen address. 
                    sta DDPoint1        ; Save it in Direct page so we can use
                    lda #$E1            ; it as a long pointer. NOTE: The screen
                    sta DDPoint1+2      ; is always in bank $E1
; Now that DDPoint1 contains the pointer we need start copying the coin data 
; to the screen, two bytes at a time.

                    ldy #$0000          ; zero the index
DD0020              lda [DDPoint2],y    ; get the next byte of data to copy
                    sta [DDPoint1],y    ; save it to the screen
                    iny                 ; bump the byte counter by 2
                    iny
                    cpy #6              ; are we done with line???
                    bne DD0020          ; if not, do another word

                    lda DDPoint2        ; Now bump up pointer to
                    clc                 ; the BitMap
                    adc #6              ; by RowBytes....
                    sta DDPoint2
                    inx                 ; bump the screen line...
                    inx                 ; by two (tbl offset)
                    cpx DDTemp          ; see if we done whole picture
                    bne DD010           ; nope do next line
                    rts
                    end

                    END
